
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using UnityEngine;
using UnityEngine.UI;

public class Utils
{
    public static bool IsUpdate = false;
    public static MonoBehaviour MainBehaviour;
    public static Func<string, object> Reflect;
    public static Action<float> OnUpdate;
    public static Action OnFixUpdate;
    public static Action OnViewUpdate;
    public static Coroutine delayCor = null;

    public static Action<string, Action> DownLoadGameFiles;
    public static Action<Action<string,string, float>> OnDownLoadGameFiles;

    public static Action<bool> OnApplicationPauseCallBack;

    public static Version version;
    /// <summary>
    /// md5file
    /// </summary>
    public static string md5file(string file)
    {
        try
        {
            FileStream fs = new FileStream(file, FileMode.Open);
            System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
            byte[] retVal = md5.ComputeHash(fs);
            fs.Close();
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < retVal.Length; i++)
            {
                sb.Append(retVal[i].ToString("x2"));
            }

            return sb.ToString();
        }
        catch (Exception ex)
        {
            throw new Exception("md5file() fail, error:" + ex.Message);
        }
    }

    private static MonoBehaviour unityBehaviour;

    public static MonoBehaviour UnityBehaviour
    {
        get { return unityBehaviour; }
        set { unityBehaviour = value; }
    }

    public static Coroutine StartCoroutine(IEnumerator enumerator)
    {
        return MainBehaviour.StartCoroutine(enumerator);
    }

    public static void StopCoroutine(Coroutine cor)
    {
        MainBehaviour.StopCoroutine(cor);
    }

    public static void StopCoroutine(string name)
    {
        MainBehaviour.StopCoroutine(name);
    }

    public static void StopAllCoroutine()
    {
        MainBehaviour.StopAllCoroutines();
    }

    public static void SetString(string key, string value)
    {
        PlayerPrefs.SetString(key, value);
    }

    public static bool HasKey(string key)
    {
        return PlayerPrefs.HasKey(key);
    }

    public static string GetString(string key, string value = null)
    {
        return PlayerPrefs.GetString(key, value);
    }


    public static void SetFloat(string key, float value)
    {
        PlayerPrefs.SetFloat(key, value);
    }

    public static float GetFloat(string key, float value = 0)
    {
        return PlayerPrefs.GetFloat(key, value);
    }


    public static void SetInt(string key, int value)
    {
        PlayerPrefs.SetInt(key, value);
    }

    public static int GetInt(string key, int value = 0)
    {
        return PlayerPrefs.GetInt(key, value);
        ;
    }

    public static void DeleteKey(string key)
    {
        PlayerPrefs.DeleteKey(key);
    }

    private static List<System.Action> mUnRegisterEventActions = new List<Action>();

    //public static void PrintStruct<T>(T data) where T : struct
    //{
    //    //// 使用反射获取结构体的字段信息
    //    //var fields = typeof(T).GetFields();

    //    //// 构造打印的字符串
    //    //string output = $"{typeof(T).Name}: ";
    //    //foreach (var field in fields)
    //    //{
    //    //    // 处理字段为数组或列表的情况
    //    //    if (field.FieldType.IsArray || (field.FieldType.IsGenericType &&
    //    //                                    field.FieldType.GetGenericTypeDefinition() == typeof(List<>)))
    //    //    {
    //    //        var collection = (IEnumerable)field.GetValue(data);
    //    //        output += $"{field.Name}: [";
    //    //        foreach (var item in collection)
    //    //        {
    //    //            // 递归处理数组或列表中的元素
    //    //            output += $"{item}, ";
    //    //        }

    //    //        output = output.TrimEnd(' ', ',') + "], ";
    //    //    }
    //    //    else
    //    //    {
    //    //        output += $"{field.Name}: {field.GetValue(data)}, ";
    //    //    }
    //    //}

    //    //// 打印到控制台
    //    //Debug.Log(output);
    //}

    /// <summary>
    /// ��ʾ��ť��״��
    /// </summary>
    /// <param name="btn"></param>
    /// <param name="isenable"></param>
    public static void OnSetButtonStatusEnable(Button btn, bool isenable)
    {
        if (btn != null)
        {
            btn.interactable = isenable;
        }
    }

    /// <summary>
    /// ��ֵת�� ��Ӧ MoneyFormatDouble NumberFormat δ��ȫ
    /// </summary>
    /// <param name="num"></param>
    /// <returns></returns>
    public static string _GMoneyFormatDouble(double num)
    {
        // double a, b;
        // a = (int)num;
        // b = num - a;
        // if (b <= 0)
        // {
        //     return a.ToString();
        // }
        // else
        // {
        //     double c = b*10 - (int)(b * 10);
        //     if (c <= 0)
        //     {
        //         return num.ToString("F1");
        //     }
        //     else
        //     {
        //         return num.ToString("F2");
        //     }
        // }

        return DevcimalToString(num, 2).ToString();
        // return num.ToString("0.##");
    }

    private static double DevcimalToString(double num, int scale)
    {
        string numtostring = num.ToString();
        
        int index = numtostring.IndexOf(".");
        int length = numtostring.Length;

        if (index != -1)
        {
            string dm = string.Format("{0}.{1}", numtostring.Substring(0, index), numtostring.Substring(index + 1, Mathf.Min(length - index - 1, scale)));
            // return System.Convert.ToDecimal(dm);
            return System.Convert.ToDouble(dm);
        }
        else
        {
            string dm = num.ToString();
            // return System.Convert.ToDecimal(dm);
            return System.Convert.ToDouble(dm);
        }
    }


    /// <summary>
    /// getConvertLocalPos
    /// </summary>
    /// <param name="srcObj"></param>
    /// <param name="desObj"></param>
    /// <returns></returns>
    public static Vector3 getConvertLocalPos(GameObject srcObj, GameObject desObj)
    {
        Vector3 srcPos = srcObj.transform.parent.TransformPoint(srcObj.transform.localPosition);
        Vector3 desPos = desObj.transform.parent.InverseTransformPoint(srcPos.x, srcPos.y, srcPos.z);
        return desPos;
    }

    //用于物体跟随鼠标移动
    public static Vector3 getTouchPositionForGameObject(Camera camera, GameObject obj)
    {
        Vector3 screenPos = camera.WorldToScreenPoint(obj.transform.position); // 目的获取z，在Start方法  
        Vector3 mousePos;
        if (Input.touchCount > 0)
        {
            mousePos = Input.GetTouch(0).position;
        }
        else
        {
            mousePos = Input.mousePosition;
        }

        mousePos.z = screenPos.z; // 这个很关键  
        Vector3 worldPos = camera.ScreenToWorldPoint(mousePos);
        return worldPos;
    }

    /// <summary>
    /// VersionValue
    /// </summary>
    /// <param name="a"></param>
    /// <param name="b"></param>
    /// <param name="c"></param>
    /// <param name="d"></param>
    /// <returns></returns>
    public static UInt32 VersionValue(UInt32 a, UInt32 b, UInt32 c, UInt32 d)
    {
        UInt32 v = 0;
        v = v | (a << 24);
        v = v | (b << 16);
        v = v | (c << 8);
        v = v | d;
        return v;
    }

    /// <summary>
    /// DelayCall
    /// </summary>
    /// <returns></returns>
    static IEnumerator DelayCall(Hashtable tb)
    {
        if (!tb.ContainsKey("time"))
        {
            yield break;
        }

        float time = (float)tb["time"];
        yield return new WaitForSeconds(time);
        if (tb.ContainsKey("callback"))
        {
            Action action = (Action)tb["callback"];
            action.Invoke();
        }

        StopCoroutine(delayCor);
    }

    /// <summary>
    /// 延迟执行
    /// </summary>
    public static void DelayToCall(float time, Action action)
    {
        if (delayCor != null)
        {
            StopCoroutine(delayCor);
            delayCor = null;
        }

        Hashtable hashtable = new Hashtable();
        hashtable.Add("time", time);
        hashtable.Add("callback", action);
        delayCor = StartCoroutine(DelayCall(hashtable));
    }

    /// <summary>
    /// CloneObject
    /// </summary>
    /// <param name="srcObj"></param>
    /// <param name="objName"></param>
    /// <returns></returns>
    public static GameObject CloneObject(GameObject srcObj, string objName)
    {
        GameObject obj =
            (GameObject)GameObject.Instantiate(srcObj, srcObj.transform.position, srcObj.transform.rotation);
        obj.name = objName;
        obj.transform.parent = srcObj.transform.parent;
        return obj;
    }

    /// <summary>
    /// CloneObject
    /// </summary>
    /// <param name="srcObj"></param>
    /// <param name="objName"></param>
    /// <param name="resetLocalScale"></param>
    /// <returns></returns>
    public static GameObject CloneObject(GameObject srcObj, string objName, bool resetLocalScale)
    {
        GameObject obj =
            (GameObject)GameObject.Instantiate(srcObj, srcObj.transform.position, srcObj.transform.rotation);
        obj.name = objName;
        obj.transform.parent = srcObj.transform.parent;
        if (resetLocalScale)
            obj.transform.localScale = Vector3.one;
        return obj;
    }

    /// <summary>
    /// 得到一个对象的克隆(二进制的序列化和反序列化)--需要标记可序列化
    /// </summary>
    public static object Clone(object obj)
    {
        MemoryStream memoryStream = new MemoryStream();
        BinaryFormatter formatter = new BinaryFormatter();
        formatter.Serialize(memoryStream, obj);
        memoryStream.Position = 0;
        return formatter.Deserialize(memoryStream);
    }
    
    /// <summary>
    /// SetButtonStateEnable
    /// </summary>
    public static async void SetButtonStateEnable(GameObject btn,bool isEnable,bool isGray = true)
    {
        if (btn == null)
        {
            Debug.LogError("btn is null");
            return;
        }

        Button[] btns = btn.transform.GetComponentsInChildren<Button>(true);
        if (btns.Length == 0)
        {      
            Debug.LogError("无button组件");
            return;
        }

        foreach (Button v in btns)
        {
            v.enabled = isEnable;
        }

        if (!isGray)
            return;
        Image[] images = btn.transform.GetComponentsInChildren<Image>();
        foreach (Image image in images)
        {
            image.material = MaterialManager.LoadMaterial("Hall/Materials", "ImageGray_mat").material;
        }
    }

    //private static Dictionary<int, string> mServerCardValueSprite = new Dictionary<int, string>();
    ///// <summary>
    ///// 获取牌面的string 根据传进来的数值，这套牌是246里面的
    ///// 服务器返回的牌值对应的Sprite
    ///// </summary>
    ///// <param name="key"></param>
    ///// <returns></returns>
    //public static string OnCardValueSprite(int key)
    //{
    //    if (mServerCardValueSprite.Count <= 0)
    //    {
    //        mServerCardValueSprite = new Dictionary<int,string>()
    //        {
    //            //--方块 A-K
    //            [1] = "Card101",[2] = "Card102",[3] = "Card103",[4] = "Card104",[5] = "Card105",
    //            [6] = "Card106",[7] = "Card107",[8] = "Card108",[9] = "Card109",[10] = "Card110",
    //            [11] = "Card111",[12] = "Card112",[13] = "Card113",
    //            //--梅花 A-K
    //            [17] = "Card201",[18] = "Card202",[19] = "Card203",[20] = "Card204",[21] = "Card205",
    //            [22] = "Card206",[23] = "Card207",[24] = "Card208",[25] = "Card209",[26] = "Card210",
    //            [27] = "Card211",[28] = "Card212",[29] = "Card213",
    //            //--红桃 A-K
    //            [33] = "Card301", [34] = "Card302", [35] = "Card303", [36] = "Card304", [37] = "Card305", 
    //            [38] = "Card306", [39] = "Card307", [40] = "Card308", [41] = "Card309", [42] = "Card310", 
    //            [43] = "Card311", [44] = "Card312", [45] = "Card313",
    //            //--黑桃 A-K
    //            [49] = "Card401", [50] = "Card402", [51] = "Card403", [52] = "Card404", [53] = "Card405",
    //            [54] = "Card406", [55] = "Card407", [56] = "Card408", [57] = "Card409", [58] = "Card410",
    //            [59] = "Card411", [60] = "Card412", [61] = "Card413"
    //        };
    //    }
        
    //    if (mServerCardValueSprite.ContainsKey(key))
    //    {
    //        return mServerCardValueSprite[key];
    //    }

    //    return "";
    //}

    private static Dictionary<int, string> mServerCardValueSprite = new Dictionary<int, string>();
    /// <summary>
    /// 获取牌面的string 根据传进来的数值，这套牌是246里面的
    /// 服务器返回的牌值对应的Sprite
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    public static string GetCardSpriteValue(int key)//OnCardValueSprite
    {
        if (mServerCardValueSprite.Count <= 0)
        {
            mServerCardValueSprite = new Dictionary<int, string>()
            {
                //--方块 A-K
                [1] = "Card101",
                [2] = "Card102",
                [3] = "Card103",
                [4] = "Card104",
                [5] = "Card105",
                [6] = "Card106",
                [7] = "Card107",
                [8] = "Card108",
                [9] = "Card109",
                [10] = "Card110",
                [11] = "Card111",
                [12] = "Card112",
                [13] = "Card113",
                //--梅花 A-K
                [17] = "Card201",
                [18] = "Card202",
                [19] = "Card203",
                [20] = "Card204",
                [21] = "Card205",
                [22] = "Card206",
                [23] = "Card207",
                [24] = "Card208",
                [25] = "Card209",
                [26] = "Card210",
                [27] = "Card211",
                [28] = "Card212",
                [29] = "Card213",
                //--红桃 A-K
                [33] = "Card301",
                [34] = "Card302",
                [35] = "Card303",
                [36] = "Card304",
                [37] = "Card305",
                [38] = "Card306",
                [39] = "Card307",
                [40] = "Card308",
                [41] = "Card309",
                [42] = "Card310",
                [43] = "Card311",
                [44] = "Card312",
                [45] = "Card313",
                //--黑桃 A-K
                [49] = "Card401",
                [50] = "Card402",
                [51] = "Card403",
                [52] = "Card404",
                [53] = "Card405",
                [54] = "Card406",
                [55] = "Card407",
                [56] = "Card408",
                [57] = "Card409",
                [58] = "Card410",
                [59] = "Card411",
                [60] = "Card412",
                [61] = "Card413"
            };
        }

        if (mServerCardValueSprite.ContainsKey(key))
        {
            return mServerCardValueSprite[key];
        }

        return "";
    }
    public static string GetCardSpritePath()
    {
        return "Hall/Textures/GameCard";
    }
}